/**
  ******************************************************************************
  * File Name          : nh3co2bsp.c
  * Description        : This file provides code for the configuration
  *                      of the USART instances.
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */
#include <stdio.h>
#include "nh3co2.h"
#include "bsp.h"

/* USART2 init function */
void NH3CO2_BspInit(void)
{
  LL_USART_InitTypeDef USART_InitStruct = {0};
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  LL_TIM_InitTypeDef TIM_InitStruct = {0};
  
/* Peripheral clock */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART4);
  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6);
  
/* USART1 GPIO PA0--->USART4_TX PA1---> USART1_RX */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_4;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_4;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* NVIC */
  NVIC_SetPriority(USART3_4_IRQn, 3);
  NVIC_EnableIRQ(USART3_4_IRQn);
  
  NVIC_SetPriority(TIM6_IRQn, 3);
  NVIC_EnableIRQ(TIM6_IRQn);
  
/* TIMER */  
  TIM_InitStruct.Prescaler = 6400-1;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 200-1;  /* 20ms */
  LL_TIM_Init(TIM6, &TIM_InitStruct);
  
  LL_TIM_EnableARRPreload(TIM6);
  
  LL_TIM_SetOnePulseMode(TIM6, LL_TIM_ONEPULSEMODE_SINGLE);
  
  LL_TIM_SetTriggerOutput(TIM6, LL_TIM_TRGO_RESET);
  
  LL_TIM_DisableMasterSlaveMode(TIM6);
  
  LL_TIM_EnableIT_UPDATE(TIM6);
  
/* USART */ 
  USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
  USART_InitStruct.BaudRate = 9600;
  USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
  USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
  USART_InitStruct.Parity = LL_USART_PARITY_NONE;
  USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
  USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
  USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
  LL_USART_Init(USART4, &USART_InitStruct);
	
	LL_USART_ConfigAsyncMode(USART4);
	
  LL_USART_SetTXFIFOThreshold(USART4, LL_USART_FIFOTHRESHOLD_1_8);
  LL_USART_SetRXFIFOThreshold(USART4, LL_USART_FIFOTHRESHOLD_1_8);
  LL_USART_DisableFIFO(USART4);
	
  LL_USART_SetRxTimeout(USART4, 5760u);                         /* (1/115200)  50ms */
  LL_USART_EnableRxTimeout(USART4);
	
	LL_USART_SetDEAssertionTime(USART4, 31);                      /* 485???????? */
  LL_USART_SetDEDeassertionTime(USART4, 31);                    /* 485???????? */
  LL_USART_SetDESignalPolarity(USART4, LL_USART_DE_POLARITY_HIGH);
  LL_USART_DisableDEMode(USART4);
	
	LL_USART_DisableDMADeactOnRxErr(USART4);
  
  LL_USART_DisableInStopMode(USART4);                           /* ????????mcu: disable */
  
	LL_USART_SetWakeUpMethod(USART4, LL_USART_WAKEUP_IDLELINE);   /* uart????:????????? */
  LL_USART_DisableMuteMode(USART4);                             /* ??uart????,????????,??????,?????????? */
  
  LL_USART_SetTXRXSwap(USART4, LL_USART_TXRX_STANDARD);         /* tx rx????:?? */
  
  LL_USART_SetTXPinLevel(USART4, LL_USART_TXPIN_LEVEL_STANDARD);
  LL_USART_SetRXPinLevel(USART4, LL_USART_RXPIN_LEVEL_STANDARD);
  LL_USART_SetBinaryDataLogic(USART4, LL_USART_BINARY_LOGIC_POSITIVE);
  
  LL_USART_DisableAutoBaudRate(USART4);
  LL_USART_DisableOneBitSamp(USART4);                           /* ??????,??3??? */
  
  LL_USART_DisableHalfDuplex(USART4);
  
  LL_USART_EnableIT_RXNE_RXFNE(USART4);
  LL_USART_EnableIT_RTO(USART4);
	
  LL_USART_Enable(USART4);
  
  /* Polling USART1 initialisation */
  while((!(LL_USART_IsActiveFlag_TEACK(USART4))) || (!(LL_USART_IsActiveFlag_REACK(USART4))))
  {
  }
	
	LL_USART_ClearFlag_RTO(USART4);
}

void NH3_UartSendBuf(const uint8_t *buf, uint32_t len)
{
	uint32_t i;
	
	for(i=0; i<len; i++)
	{
    USART4->TDR = (buf[i]& (uint16_t)0x01FFU);
    while(READ_BIT(USART4->ISR, USART_ISR_TXE_TXFNF) != (USART_ISR_TXE_TXFNF));
	}
	
	while(READ_BIT(USART4->ISR, USART_ISR_TC) != (USART_ISR_TC));
}

/**
  * @brief This function handles USART2 global interrupt.
  */
void USART3_4_IRQHandler(void)
{
	if(READ_BIT(USART4->ISR, USART_ISR_RXNE_RXFNE) != 0)
	{
    TIM6->CR1 &= (~TIM_CR1_CEN);
    
		NH3CO2_RecvIsr(USART4->RDR);
    
    TIM6->CNT = 0x00u;
    TIM6->CR1 |= TIM_CR1_CEN;
	}
  
  if(READ_BIT(USART4->ISR, USART_ISR_ORE) != 0)
	{
    LL_USART_ClearFlag_ORE(USART4);
  }
}

void TIM6_IRQHandler(void)
{
  if(LL_TIM_IsActiveFlag_UPDATE(TIM6) != 0)
	{
		LL_TIM_ClearFlag_UPDATE(TIM6);
    
    NH3CO2_BreakIsr();
  }
}
